from operator import and_

from info import db
from info.constants import CLICK_RANK_MAX_NEWS
from info.models import User, News, Comment, CommentLike
from info.response_code import RET
from info.utils.common import login_user_data
from . import news_blu
from flask import render_template, session, g, abort, request, jsonify


# 添加一个路由 关注和取消关注
@news_blu.route('/followed_user', methods=['POST'])
@login_user_data
def followed_user():
    # 根据传递过来的参数 录入数据库
    # 1.接收参数
    req_dict = request.json
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    # 2. 判断参数是否为空
    '''
    user_id	 
    action
    '''
    user_id = req_dict.get('user_id')
    action = req_dict.get('action')

    if not user_id:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if not action:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if action not in ('follow', 'unfollow'):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 3. 先寻找 关注的用户是否存在
    target_user = User.query.get(user_id)
    if not target_user:
        return jsonify(errno=RET.PARAMERR, errmsg='关注用户不存在')
    # 4. 根据这个关注 和取消关注
    if action == 'follow':
        # 关注的时候做的操作
        if target_user.followers.filter(User.id == g.user.id).count() > 0:
            return jsonify(errno=RET.PARAMERR, errmsg='已经关注了该用户')
        target_user.followers.append(g.user)
        db.session.commit()
    else:
        # 取消关注做的操作
        if target_user.followers.filter(User.id == g.user.id).count() > 0:
            target_user.followers.remove(g.user)
            db.session.commit()
    return jsonify(errno=RET.OK, errmsg='关注成功')


# 新闻点赞
@news_blu.route('/comment_like', methods=['POST'])
@login_user_data
def comment_like():
    '''
    comment_id	int	是	评论id
    news_id	int	是	新闻id
    action	string	是	点赞操作类型：add(点赞)，remove(取消点赞)
    :return:
    '''
    # 1.通过post获取参数
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    req_dict = request.json
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    comment_id = req_dict.get('comment_id')
    news_id = req_dict.get('news_id')
    action = req_dict.get('action')
    # 将数据转成int类型
    try:
        news_id = int(news_id)
        comment_id = int(comment_id)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 判断 action add(点赞)，remove(取消点赞)
    if action not in ('add', 'remove'):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 判断新闻是否存在
    comment_dic = Comment.query.get(comment_id)
    if not comment_dic:
        return jsonify(errno=RET.PARAMERR, errmsg='新闻评论不存在')
    if action == 'add':
        # 如果是点赞往评论中的like_count+1 并往commt_like中添加一条数据
        comment_dic.like_count += 1
        comment_like = CommentLike()
        comment_like.user_id = user.id
        comment_like.comment_id = comment_id
        db.session.add(comment_like)
        db.session.commit()
        return jsonify(errno=RET.OK, errmsg='点赞成功')
    else:
        # 如果是取消赞往评论中的like_count-1  并往commt_like中删除一条数据
        comment_dic.like_count -= 1
        result_comment_like = CommentLike.query.filter(and_(CommentLike.user_id == user.id,
                                                            CommentLike.comment_id == comment_id)).first()
        db.session.delete(result_comment_like)
        db.session.commit()
        return jsonify(errno=RET.OK, errmsg='取消点赞成功')


# 添加新闻评论
@news_blu.route('/news_comment', methods=['POST'])
@login_user_data
def news_comment():
    '''
    news_id	int	是	新闻id
    comment	string	是	评论内容
    parent_id	int	否	回复的评论的id
    :return:
    '''
    # 1 接受参数
    user = g.user
    req_dict = request.json
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    news_id = req_dict.get('news_id')
    comment = req_dict.get('comment')
    # parent_id 要注意这个参数可能为空
    parent_id = req_dict.get('parent_id')
    # 2 判断参数
    if not all([news_id, comment]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # news_id转换成int类型
    try:
        news_id = int(news_id)
        if parent_id:
            parent_id = int(parent_id)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 3  判断新闻是否存在 如果存在就添加新闻
    news = News.query.get(news_id)
    if not news:
        return jsonify(errno=RET.PARAMERR, errmsg='不存在这条新闻')
    # 4 根据这条新闻添加评论
    comment_dic = Comment()
    comment_dic.user_id = user.id
    comment_dic.news_id = news_id
    comment_dic.content = comment
    # 判断 parent_id 是否有值
    if parent_id:
        comment_dic.parent_id = parent_id
    db.session.add(comment_dic)
    db.session.commit()
    return jsonify(errno=RET.OK, errmsg='评论成功', comment=comment_dic.to_dict())


# 新闻收藏功能
@news_blu.route('/news_collect', methods=['POST'])
@login_user_data
def news_collect():
    '''
        步骤
            1接受参数
                news_id	int	是	新闻id
                action	string	是	指定两个值：'collect', 'cancel_collect'
            2 判断 用户是否存在  news_id action 是否有参数并且是不是指定两个值
            3.根据action collect 就添关注  cancel_collect 取消关注
            4.返回成功数据
    :return:
    '''
    # 1接受参数
    user = g.user
    req_dict = request.json
    if not req_dict:
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    news_id = req_dict.get('news_id')
    action = req_dict.get('action')
    # 2 判断 用户是否存在  news_id action 是否有参数并且是不是指定两个值
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if action not in ('collect', 'cancel_collect'):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 寻找要关注的新闻
    news = News.query.get(news_id)
    if not news:
        return jsonify(errno=RET.PARAMERR, errmsg='没有这个新闻')
    #  3.根据action collect 就添关注  cancel_collect 取消关注
    if action == 'collect':
        # 用户第一次关注 才添加关注
        if news not in user.collection_news:
            # 添加关注
            user.collection_news.append(news)
        else:
            return jsonify(errno=RET.PARAMERR, errmsg='已经关注过一次')
    else:
        # 取消关注
        if news in user.collection_news:
            # 移除关注
            user.collection_news.remove(news)
        else:
            return jsonify(errno=RET.PARAMERR, errmsg='从未关注过不能取消')
    db.session.commit()
    return jsonify(errno=RET.OK, errmsg='收藏或者取消收藏处理成功')


# 新闻详细的首页

@news_blu.route('/<int:news_id>')
@login_user_data
def news_index(news_id):
    '''
        @user_login_data
        已下代码都是重复的代码 ，需要将其提取出来放在装饰器中，方便下次使用
        # 判断用户是否登录
        user_id = session.get('user_id')
        user = None
        if user_id:
            # 判断user_id为空 判断数据库中是否有这么一个人（假设这个人被删除就不能找到）
            user = User.query.get(user_id)
        # 为什么能够使用user的原因是因为在父模板中有使用过user ，所以才可以在新闻详细页中使用
    '''
    # 需要获取装饰器中的 user
    # if g.user:
    #     print(g.user)
    user = g.user
    print(g.user)

    # 显示点击排行
    # 查询新闻中点击量最高的降序排列 获取前10条数据CLICK_RANK_MAX_NEWS
    news_click_list = News.query.order_by(News.clicks.desc()).limit(CLICK_RANK_MAX_NEWS)

    # 根据新闻id 获取新闻
    news = News.query.get(news_id)
    # 判断新闻是否存在
    if not news:
        # 页面不存在
        abort(404)

    # 新闻点击每次进来以后自增
    news.clicks += 1
    db.session.commit()

    # 判断用户是否收藏新闻
    is_collected = False
    if user:
        if news in user.collection_news:
            is_collected = True
    # 显示用户评论列表
    # 根据新闻id来获取当前新闻的所有评论
    result_list = Comment.query.filter(Comment.news_id == news_id)
    comment_list = []
    for comment in result_list:
        comment_list.append(comment.to_dict())

    # 显示当前用户是否点赞
    '''
    步骤：
    1.查找当前新闻中所有的评论id
    2 查找评论中的点赞
    3. 找所有点赞以后的id
    '''
    if user:
        # 1.查找当前新闻中所有的评论id
        comment_id_list = [t['id'] for t in comment_list]
        # 2 查找评论中的点赞
        comment_like_list = CommentLike.query.filter(CommentLike.comment_id.in_(comment_id_list),
                                                     CommentLike.user_id == user.id).all()
        # 3. 找所有点赞以后的id
        comment_like_id_list = [t1.comment_id for t1 in comment_like_list]

        # 4 循环评论 给评论中每一个元素都添加一个属性，用来表示当前用户点过了赞
        for c1 in comment_list:
            if c1['id'] in comment_like_id_list:
                c1['is_like'] = True
    # 是否关注过当前作者
    # 如果关注当前作者 添加一个判断条件  is_follower 用来判断当前用户是否关注
    is_follower = False  # 没有关注
    # 是否关注过当前作者
    if news.user and user:
        if news.user in user.followers:
            is_follower = True
    return render_template('news/detail.html',
                           user=user,
                           news_click_list=news_click_list,
                           news=news.to_dict(),
                           is_collected=is_collected,
                           is_follower=is_follower,
                           comment_list=comment_list)
